/**
 * Solar Core
 */
function SolarCore ()
{
	var thi$ = this;
	this._class = arguments.callee;

	var _source =
	{
	    'path' : "",
	    'script' : null
	};

	/**
	 * Constructor
	 */
	function construct ()
	{
		// Check for 'solarcore'
		try
		{
			eval ("solarcore");

			_installed = true;
		}
		catch (theError)
		{
			_installed = false;
		}

		if (_installed)
		{
			if (solarcore._uid != UID)
			{
				throw "An unknown version of Solar Core is already installed.";
			}
			else
			{
				throw "Solar Core is already installed.";
			}
		}
		else
		{
			solarcore = thi$;

			createCore ();

			// Retrieve the source of ignition
			var scripts = document.getElementsByTagName ("script");
			_source.script = scripts[scripts.length - 1];
			_source.path = _source.script.src.split ("/");
			_source.path.pop ();
			_source.path = _source.path.join ("/");

			// Pour in agents

			window.setTimeout (startFusion, 100);
		}
	}

	/***********************************************************************************************************************************************************
	 * solarcore.core
	 **********************************************************************************************************************************************************/
	function createCore ()
	{
		solarcore.core = {};

		/*******************************************************************************************************************************************************
		 * Environment
		 ******************************************************************************************************************************************************/
		solarcore.core.Environment = function ()
		{
		};
		solarcore.core.Environment.init = function ()
		{
			var dataBrowser = [
			{
			    'string' : navigator.userAgent,
			    'subString' : "Chrome",
			    'identity' : "Chrome"
			},
			{
			    'string' : navigator.userAgent,
			    'subString' : "OmniWeb",
			    'versionSearch' : "OmniWeb/",
			    'identity' : "OmniWeb"
			},
			{
			    'string' : navigator.vendor,
			    'subString' : "Apple",
			    'identity' : "Safari",
			    'versionSearch' : "Version"
			},
			{
			    'prop' : window.opera,
			    'identity' : "Opera",
			    'versionSearch' : "Version"
			},
			{
			    'string' : navigator.vendor,
			    'subString' : "iCab",
			    'identity' : "iCab"
			},
			{
			    'string' : navigator.vendor,
			    'subString' : "KDE",
			    'identity' : "Konqueror"
			},
			{
			    'string' : navigator.userAgent,
			    'subString' : "Firefox",
			    'identity' : "Firefox"
			},
			{
			    'string' : navigator.vendor,
			    'subString' : "Camino",
			    'identity' : "Camino"
			},
			{ // for newer Netscapes (6+)
			    'string' : navigator.userAgent,
			    'subString' : "Netscape",
			    'identity' : "Netscape"
			},
			{
			    'string' : navigator.userAgent,
			    'subString' : "MSIE",
			    'identity' : "Explorer",
			    'versionSearch' : "MSIE"
			},
			{
			    'string' : navigator.userAgent,
			    'subString' : "Gecko",
			    'identity' : "Mozilla",
			    'versionSearch' : "rv"
			},
			{ // for older Netscapes (4-)
			    'string' : navigator.userAgent,
			    'subString' : "Mozilla",
			    'identity' : "Netscape",
			    'versionSearch' : "Mozilla"
			} ];

			var dataOS = [
			{
			    'string' : navigator.platform,
			    'subString' : "Win",
			    'identity' : "Windows"
			},
			{
			    'string' : navigator.platform,
			    'subString' : "Mac",
			    'identity' : "Mac"
			},
			{
			    'string' : navigator.userAgent,
			    'subString' : "iPhone",
			    'identity' : "iPhone/iPod"
			},
			{
			    'string' : navigator.platform,
			    'subString' : "Linux",
			    'identity' : "Linux"
			} ];

			this.searchString = function (data)
			{
				for ( var i = 0; i < data.length; i++)
				{
					var dataString = data[i].string;
					var dataProp = data[i].prop;
					this.versionSearchString = data[i].versionSearch || data[i].identity;
					if (dataString)
					{
						if (dataString.indexOf (data[i].subString) != -1)
						{
							return data[i].identity;
						}
					}
					else if (dataProp)
					{
						return data[i].identity;
					}
				}
			};

			this.searchVersion = function (dataString)
			{
				var index = dataString.indexOf (this.versionSearchString);
				if (index == -1)
				{
					return "0.0";
				}

				return parseFloat (dataString.substring (index + this.versionSearchString.length + 1));
			};

			this.browser =
			{
			    'name' : this.searchString (dataBrowser) || "Unknown browser",
			    'version' : this.searchVersion (navigator.userAgent) || this.searchVersion (navigator.appVersion) || "0.0"
			};

			this.operatingSystem =
			{
				'name' : this.searchString (dataOS) || "Unknown operating system"
			};
		};

		/*******************************************************************************************************************************************************
		 * Console
		 ******************************************************************************************************************************************************/
		solarcore.core.Console = function ()
		{
			var _console = (!console) ? {} : console;

			if (typeof (_console.log) != "function")
			{
				_console.log = function (msg)
				{
					window.setTimeout (function ()
					{
						throw msg;
					}, 0);
				};
			}

			this.log = function (msg, useToString)
			{
				if (msg && useToString && (typeof (msg.toString) == "function"))
				{
					msg = msg.toString ();
				}
				_console.log (msg);
			};
		};
		solarcore.core.Console.init = function ()
		{
			window.console = new this ();
		};

		/*******************************************************************************************************************************************************
		 * JSML processor
		 ******************************************************************************************************************************************************/
		solarcore.core.JSMLProcessor = function ()
		{
			var $elf = arguments.callee;

			var _code =
			{
			    'precompiled' : "",
			    'raw' : "",
			    'references' : [],
			    'temp' : [],
			    'final' : ""
			};
			var _imports = [];
			var _importsByURI = {};
			var _packages = [];
			var _packagesById = {};
			var _packagesByURI = {};
			var _references = {};
			var _$elf = "";
			var _source = "";
			var _uri = "Unknown";

			function transformXML (xmlDocument, xslDocument)
			{
				var result = "";

				if (typeof (XSLTProcessor) != "undefined")
				{ // FF, Safari, Chrome etc
					var resultDocument = null;
					var xsltProcessor = new XSLTProcessor ();

					if (xsltProcessor.transformDocument)
					{
						xsltProcessor.transformDocument (xmlDocument, xslDocument, resultDocument, null);

						var serializer = new XMLSerializer ();
						result = serializer.serializeToString (resultDocument);
					}
					else
					{
						xsltProcessor.importStylesheet (xslDocument);
						resultDocument = xsltProcessor.transformToFragment (xmlDocument, document);

						result = resultDocument.textContent;
					}
				}
				else if (typeof (xmlDocument.transformNode) != "undefined")
				{ // IE6, IE7, IE8
					result = xmlDocument.transformNode (xslDocument);
				}
				else
				{
					try
					{ // IE9 and grater
						if (window.ActiveXObject)
						{
							var msXSLTemplate = new ActiveXObject ("Msxml2.XSLTemplate");
							var msXSLDocument = new ActiveXObject ("Msxml2.FreeThreadedDOMDocument");
							msXSLDocument.loadXML (xslDocument.xml);
							msXSLTemplate.stylesheet = msXSLDocument;
							var xsltProcessor = msXSLTemplate.createProcessor ();
							xsltProcessor.input = xmlDocument;
							xsltProcessor.transform ();
							result = xsltProcessor.output;
						}
					}
					catch (e)
					{
						// alert ("The type [XSLTProcessor] and the function [XmlDocument.transformNode] are not supported by this browser, can't transform XML
						// document to HTML string!");
						alert (e);
						return null;
					}

				}

				return result;
			}

			function registerImport (uri)
			{
				if (!_importsByURI.hasOwnProperty (uri))
				{
					_imports.push ('"' + uri + '"');
					_importsByURI[uri] = true;
				}
			}

			function registerPackage (name, uri)
			{
				var packageAlias = name.full.replace (name.suffix, "");

				if (!_packagesByURI.hasOwnProperty (uri))
				{
					var packageData =
					{
					    'alias' : packageAlias,
					    'uri' : uri
					};

					_packages.push (uri);
					_packagesByURI[uri] = packageData;
					_references[packageAlias] = uri;
				}
			}

			function compile ()
			{
				precompile ();

				_$elf = _uri;
				for ( var reference in _references)
				{
					_$elf = _$elf.replace (_references[reference], "$" + reference);
				}
				_$elf = _$elf.split ('/').join ('.');

				_code.raw = transformXML (_source.result.xml, $elf.jsmlCompiler);

				_code.temp.push ('solarcore.import([');
				_code.temp.push (_imports.join (','));
				_code.temp.push ('],function(){');

				_code.temp.push (_code.raw.replace (/\{\$self\}/g, _$elf));

				_code.temp.push ('});');

				return;

				compiledCode.finalCode.push ('solarcore.import([');
				compiledCode.finalCode.push (compiledCode.importCodes.join ('\n'));

				compiledCode.$elf = compiledCode.uri;
				for ( var ref in compiledCode.refs)
				{
					compiledCode.$elf = compiledCode.$elf.replace (compiledCode.refs[ref], "$" + ref);
				}
				compiledCode.$elf = compiledCode.$elf.split ('/').join ('.');

				compiledCode.finalCode.push ([
				                              '],',
				                              'function(){\n',
				                              compiledCode.refCodes.join ('\n'),
				                              '\n',
				                              rawCode.replace (/\{\$self\}/g, compiledCode.$elf),
				                              'solarcore.resourceManager.resourceReady("' + compiledCode.uri + '");',
				                              '}' ].join (''));
				compiledCode.finalCode.push (');');

				return compiledCode;
			}

			function precompile ()
			{
				_code.precompiled = transformXML (_source.result.xml, $elf.jsmlPrecompiler).replace (/[\n\s\t]+/gi, "");

				try
				{
					eval (_code.precompiled);
				}
				catch (exception)
				{
					throw (_uri + ": " + exception);
				}

				console.log (_uri);
				console.log (_references);

				return;

				var parts = precompiled.split ("=**=");

				for ( var count = 0; count < parts.length; count++)
				{
					if (parts[count] != "")
					{
						var tokens = parts[count].split ("=*=");

						switch (tokens[0]) {
							case "$ref":
								compiledCode.refs[tokens[1].split (':')[0]] = tokens[3];
							break;

							case "$import":
								var tokenParts = tokens[1].split (':');
								var alias = tokenParts.join ('.');
								tokenParts[0] = compiledCode.refs[tokenParts[0]];
								compiledCode.imports[alias] = tokenParts.join ('/');
							break;
						}
					}
				}

				for ( var refKey in compiledCode.refs)
				{
					compiledCode.refCodes.push ('var $' + refKey + '=solarcore.package("' + compiledCode.refs[refKey] + '");');
				}

				var imports = [];
				for ( var importKey in compiledCode.imports)
				{
					imports.push ('"' + compiledCode.imports[importKey] + '"');
				}
				compiledCode.importCodes.push (imports.join (','));
			}

			this.process = function (uri)
			{
				_uri = uri;
				_code.temp.push ("/* ", " * " + _uri, " */", "");
				_source = solarcore.resourceManager.getResource (_uri);

				compile ();

				_code.final = _code.temp.join ("\n");
				document.getElementById ('code').value = _code.final;

				return;

				var compiledCode =
				{
				    'finalCode' : [ "/* ", " * " + uri, " */", "" ],
				    'imports' : {},
				    'importCodes' : [],
				    'refs' : {},
				    'refCodes' : [],
				    'uri' : uri,
				    'source' : solarcore.resourceManager.getResource (uri)
				};

				compile (compiledCode);
				compiledCode.source.result.compiled = compiledCode.finalCode.join ("\n");

				// console.log (compiledCode.source.result.compiled);

				document.getElementById ('code').value = compiledCode.source.result.compiled;

				compiledCode.source.jsElement = document.createElement ("script");
				compiledCode.source.jsElement.id = "" + uri + "";
				compiledCode.source.jsElement.innerHTML = compiledCode.source.result.compiled;

				try
				{
					eval ("if (false){" + compiledCode.source.result.compiled + "}");

					document.head.appendChild (compiledCode.source.jsElement);
				}
				catch (e)
				{
					throw uri + ": " + e;
				}

				// eval (compiledCode.source.result.compiled);
				// var script = document.createElement ("script");
				// script.id = uri;
				// script.innerHTML = "eval(solarcore.resourceManager.getResource ('" + uri + "').result.compiled);";
				// document.head.appendChild (script);
				/*
				 * eval ("solarcore.resourceManager.getResource ('" + uri + "')").postProcess = function () { eval (this.result.compiled); };
				 */

				// window.setTimeout ("solarcore.resourceManager.getResource ('" + uri + "').postProcess()", 0);
			};
		};
		solarcore.core.JSMLProcessor.isReady = false;
		solarcore.core.JSMLProcessor.jsmlc = null;
		solarcore.core.JSMLProcessor.jsmli = null;
		solarcore.core.JSMLProcessor.init = function ()
		{
			if (!this.isReady)
			{
				var uriJSMLCompiler = "library://solarcore/core/JSMLCompiler.xsl";
				var uriJSMLPrecompiler = "library://solarcore/core/JSMLPrecompiler.xsl";

				solarcore.resourceManager.load (uriJSMLCompiler, solarcore.core.ResourceManager.TYPE_XML, null, null, true);
				solarcore.resourceManager.load (uriJSMLPrecompiler, solarcore.core.ResourceManager.TYPE_XML, null, null, true);

				this.jsmlCompiler = solarcore.resourceManager.getResource (uriJSMLCompiler).result.xml;
				this.jsmlPrecompiler = solarcore.resourceManager.getResource (uriJSMLPrecompiler).result.xml;

				this.isReady = true;
			}
		};

		/*******************************************************************************************************************************************************
		 * Resource manager
		 ******************************************************************************************************************************************************/
		solarcore.core.ResourceManager = function ()
		{
			var thi$ = this;
			var $elf = arguments.callee;

			var _resourceProviders = [];
			var _resources = {};

			this.addResourceProvider = function (resourceProvider)
			{
				_resourceProviders.push (resourceProvider);
			};

			this.getResource = function (uri)
			{
				return _resources[uri];
			};

			this.load = function (uri, resType, onLoaded, onReady, synchronous)
			{
				if (_resources[uri])
				{
				}
				else
				{
					_resources[uri] =
					{
					    'onLoaded' : onLoaded,
					    'onReady' : onReady,
					    'resType' : resType,
					    'size' : 0,
					    'status' : $elf.STATUS_LOADING,
					    'result' : {}
					};

					var xmlHTTP = (window.XMLHttpRequest) ? new XMLHttpRequest () : new ActiveXObject ("Microsoft.XMLHTTP");

					var responseType = "text";
					var url = this.resolveURI (uri);

					switch (resType) {
						case $elf.TYPE_IMAGE:
						break;

						case $elf.TYPE_JAVA_SCRIPT:
							url += ".xml";
						break;

						case $elf.TYPE_JSML:
							url += ".xml";
							responseType = "msxml-document";
						break;

						case $elf.TYPE_XML:
							responseType = "msxml-document";
						break;
					}

					if (synchronous)
					{
						xmlHTTP.open ("HEAD", url + "?" + new Date ().getTime (), false);
						if ((solarcore.core.Environment.browser.name == "Explorer") && (solarcore.core.Environment.browser.version > 9))
						{
							xmlHTTP.responseType = responseType;
						}
						xmlHTTP.send (new Date ().getTime ());
						thi$.setResourceSize (uri, xmlHTTP.getResponseHeader ("Content-Length"));
					}

					xmlHTTP.onreadystatechange = function ()
					{
						switch (this.readyState) {
							case 2:
								thi$.setResourceSize (uri, xmlHTTP.getResponseHeader ("Content-Length"));
							break;

							case 4:
								_resources[uri].result.text = xmlHTTP.responseText;
								_resources[uri].result.xml = xmlHTTP.responseXML;

								thi$.resourceLoaded (uri);
							break;
						}
					};

					xmlHTTP.open ("GET", url + "?" + (_resources[uri].size != 0 ? _resources[uri].size : new Date ().getTime ()), !synchronous);
					xmlHTTP.send ("?" + _resources[uri].size);
				}
			};

			this.resolveURI = function (uri)
			{
				var resolvedURI = uri;

				for ( var count = 0; count < _resourceProviders.length; count++)
				{
					var resourceProvider = _resourceProviders[count];
					resolvedURI = resolvedURI.replace (resourceProvider.id, resourceProvider.url);
				}

				return resolvedURI;
			};

			this.resourceLoaded = function (uri)
			{
				if (_resources[uri])
				{
					var isReady = false;
					var resource = _resources[uri];

					resource.status = $elf.STATUS_LOADED;

					if (typeof (resource.onLoaded) == "function")
					{
						resource.onLoaded ();
					}

					switch (resource.resType) {
						case $elf.TYPE_IMAGE:
							isReady = true;
						break;

						case $elf.TYPE_JAVA_SCRIPT:
						break;

						case $elf.TYPE_JSML:
							_resources[uri].processor = new solarcore.core.JSMLProcessor ();
							_resources[uri].processor.process (uri);
						break;

						case $elf.TYPE_XML:
							isReady = true;
						break;
					}

					if (isReady)
					{
						this.resourceReady (uri);
					}
				}
			};

			this.resourceReady = function (uri)
			{
				if (_resources[uri])
				{
					var resource = _resources[uri];

					resource.status = $elf.STATUS_READY;

					if (typeof (resource.onReady) == "function")
					{
						resource.onReady ();
					}
				}
			};

			this.setResourceSize = function (uri, size)
			{
				if (_resources[uri])
				{
					_resources[uri].size = size;
					// console.log (size);
				}
			};
		};
		solarcore.core.ResourceManager.STATUS_LOADING = 1;
		solarcore.core.ResourceManager.STATUS_LOADED = 2;
		solarcore.core.ResourceManager.STATUS_READY = 4;
		solarcore.core.ResourceManager.TYPE_IMAGE = 1;
		solarcore.core.ResourceManager.TYPE_JAVA_SCRIPT = 2;
		solarcore.core.ResourceManager.TYPE_JSML = 4;
		solarcore.core.ResourceManager.TYPE_XML = 8;
		solarcore.core.ResourceManager.instance = null;
		solarcore.core.ResourceManager.init = function ()
		{
			var resourceManager = new solarcore.core.ResourceManager ();

			solarcore.addResourceProvider = function (resourceProvider)
			{
				resourceManager.addResourceProvider (resourceProvider);
			};

			solarcore.getResource = function (uri)
			{
				return resourceManager.getResource (uri);
			};

			solarcore.load = function (uri, resType, onLoaded, onReady, synchronous)
			{
				resourceManager.load (uri, resType, onLoaded, onReady, synchronous);
			};

			this.instance = resourceManager;
			solarcore.resourceManager = resourceManager;
		};
	}

	/**
	 * Initialize
	 */
	function init ()
	{
		// createDefaultStyles ();

		solarcore.core.Console.init ();
		solarcore.core.Environment.init ();

		render ();

		solarcore.core.ResourceManager.init ();
		solarcore.addResourceProvider (
		{
		    'id' : "library://solarcore",
		    'url' : _source.path
		});
		solarcore.core.JSMLProcessor.init ();

		solarcore.load ("library://solarcore/core/Loader", solarcore.core.ResourceManager.TYPE_JSML, function ()
		{
			// console.log (this.result.text);
		}, function ()
		{
			// console.log (this.result.compiled);
			document.getElementById ('code').value = this.result.compiled;
		});
	}

	/**
	 * Render
	 */
	function render ()
	{
		window.onscroll = function ()
		{
			window.scrollTo (0, 0);
		};

		var icon = document.createElement ("link");
		icon.rel = "shortcut icon";
		icon.href = _source.path + "/resources/solarcore.ico";
		document.getElementsByTagName ("HEAD").item (0).appendChild (icon);
	}

	/**
	 * Start the fusion
	 */
	function startFusion ()
	{
		if (document && document.body && solarcore)
		{
			try
			{
				for ( var key in HTMLPrototype)
				{
					(!document.body[key]) && (document.body[key] = HTMLPrototype[key]);
				}
				document.body.className = "SolarCore";
			}
			catch (theError)
			{
			}

			window.setTimeout (function ()
			{
				var logo = document.createElement ("img");
				logo.onload = function ()
				{
					window.setTimeout (function ()
					{
						try
						{
							document.body.removeChild (logo);
						}
						catch (theError)
						{
						}
					}, 0);

					init ();
				};
				logo.style.visibility = "hidden";
				logo.src = _source.path + "/resources/solarCore32.gif";
				document.body.appendChild (logo);
			}, 10);
		}
		else
		{
			window.setTimeout (startFusion, 100);
		}
	}

	/*
	 * this.Fusion = function () { this._class = arguments.callee; function construct () { ignite (); } function ignite () { } }; this.Fusion.$tatic ( { '_uid' :
	 * "b1add1ca-fed7-42a9-8de0-c7a7b97a93e2" });
	 */

	// Constructs the Core
	construct ();
}
SolarCore._uid = "ac045353-c31d-44c1-a5e7-93d874c1fd62";

// Create the Core
new SolarCore ();

if (false)
{
	solarcore = {};
}

// Create SolarCore
/*
 * try { var UID = "ac045353-c31d-44c1-a5e7-93d874c1fd62"; eval ("solarcore"); if (solarcore._uid != UID) { throw "An unknown version of Solar Core is already
 * installed."; } else { throw "Solar Core is already installed."; } } catch (theError) { window.solarcore = new SolarCore (); }
 */